﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

namespace K9Tools.Abstractions.Extensions;

public static class CommonExtensions
{
    public static bool IsValueNull(this object? obj)
    {
        if (obj == null) return true;
        var type = obj.GetType();
        if (type.IsValueType)
        {
            return obj switch
            {
                int i => i == 0,
                long l => l == 0L,
                short s => s == 0,
                float f => f.AlmostEquals(0F),
                double d => d.AlmostEquals(0D),
                DateTime dt => dt == default,
                _ => false
            };
        }

        if (type == typeof(DateTime?))
        {
            var dt2 = (DateTime?)obj;
            return dt2.Value == default;
        }


        if (obj is string str)
        {
            return string.IsNullOrWhiteSpace(str);
        }

        return false;
    }

    public static bool AlmostEquals(this double double1, double double2, double precision = 0.0000001)
    {
        return Math.Abs(double1 - double2) <= precision;
    }

    public static bool AlmostEquals(this float float1, float float2, float precision = 0.0000001F)
    {
        return Math.Abs(float1 - float2) <= precision;
    }

    public static void Extends<TKey, TValue>(this Dictionary<TKey, TValue> a, Dictionary<TKey, TValue> b)
        where TKey : notnull
    {
        foreach (var key in a.Keys)
        {
            if (b.ContainsKey(key))
            {
                var value = b[key];
                if (!value.IsValueNull())
                {
                    a[key] = b[key];
                }
            }
        }
    }

    public static DateTime ToDayStart(this DateTime time)
    {
        return new DateTime(time.Year, time.Month, time.Day);
    }

    public static string? GetDescription(this Type type, bool inherit = false)
    {
        return type.TryGetCustomAttribute<DescriptionAttribute>(inherit, out var desc)
              ? desc!.Description : null;
    }

    public static string? GetDescription(this PropertyInfo propertyInfo, bool inherit = false)
    {
        return propertyInfo.TryGetCustomAttribute<DescriptionAttribute>(inherit, out var desc)
              ? desc!.Description : null;
    }
}